package com.kabao.javafx.rain;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RainApp extends Application {
    //雨滴
    static final Image RAINDROP_IMG = new Image(RainApp.class.getResource("/img/rain/raindrop.png").toExternalForm()
            , 8, 25, true, true);

    //水波
    static final Image RIPPLE_IMG = new Image(RainApp.class.getResource("/img/rain/ripple.png").toExternalForm()
            , 25, 25, true, true);

    //雪花数量
    private List<Rain> rainList = new ArrayList<>(2000);
    private int flakeNum = 300;
    private int w = 2048;
    private int h = 1367;

    private int POOL_HEIGHT = 1000;
    private int POOL_UP_HEIGHT = 885;

    private Random random = new Random();
    Text textFps =new Text("FPS: 0");
    Pane root;

    /**
     * 雨的两种状态
     */
    enum RainStatus{
        //雨滴
        RAINDROP,
        //水波
        RIPPLE
    }

    class Rain extends ImageView {
        private double verSpeed;//下落速度
        private double horSpeed; //水平移动速度

        private double maxY;//最大的雨滴高度

        private RainStatus status;

        public double getMaxY() {
            return maxY;
        }

        public void setMaxY(double maxY) {
            this.maxY = maxY;
        }

        public Rain() {
            //初始状态设置为雨滴
            super(RAINDROP_IMG);
            this.status = RainStatus.RAINDROP;
        }

        public RainStatus getStatus() {
            return status;
        }

        public void setStatus(RainStatus status) {
            this.status = status;
        }

        public double getVerSpeed() {
            return verSpeed;
        }

        private void changeStatus(){
            //雨点 改变为水波
            this.status = (this.status == RainStatus.RAINDROP ? RainStatus.RIPPLE : RainStatus.RAINDROP);
            if(status == RainStatus.RAINDROP){
                setImage(RAINDROP_IMG);
            }else {
                setImage(RIPPLE_IMG);
            }
        }

        public void setVerSpeed(double verSpeed) {
            this.verSpeed = verSpeed;
        }

        public double getHorSpeed() {
            return horSpeed;
        }

        public void setHorSpeed(double horSpeed) {
            this.horSpeed = horSpeed;
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = new Pane();
        textFps.setTextOrigin(VPos.TOP);
        textFps.setFill(Color.WHITE);
        textFps.setFont(Font.font(35));

        root.setStyle("-fx-background-color: #f0f0f0;"); // 灰色背景，便于观察

        Image image = new Image(getClass().getResource("/img/rain/rain_bg.jpeg").toExternalForm());
        ImageView imageView = new ImageView(image);
        //自适应大小
        imageView.fitWidthProperty().bind(root.widthProperty());
        imageView.fitHeightProperty().bind(root.heightProperty());
        //保持宽高比，避免拉伸变形
        imageView.setPreserveRatio(false);
        // 缩放时平滑显示，避免锯齿,可选：如果图片比例与容器不符，设置填充方式（如居中）
        imageView.setSmooth(true);
        root.getChildren().add(imageView);
        root.getChildren().add(textFps);

        initRain();
        primaryStage.setScene(new Scene(root,w,h));
        primaryStage.setTitle("雨滴效果");
        primaryStage.show();

        AnimationTimer animationTimer = new AnimationTimer() {
            int times;
            boolean reserve;
            long lastTime = System.nanoTime();
            //一秒= 10亿纳秒
            long ONE_SECOND = 1_000_000_000;
            //差值
            double duration ;
            //fps
            int fps;

            @Override
            public void handle(long now) {
                fps++;
                duration=  duration + (now - lastTime);
                if (duration >= ONE_SECOND) {
                    textFps.setText("FPS: " + fps);
                    fps = 0;
                    duration = 0;
                }
                lastTime = now;

                //每一帧都会被调用一次,3秒钟移动一次 也即 3*200 = 600,fps为200大概
                times++;
                if (times % 200 == 0) {
                    reserve = true;
                    times = 0;
                }

                for (Rain raindrop : rainList) {
                    if(raindrop.getStatus() == RainStatus.RAINDROP){
                        //下落速度
                        raindrop.setY(raindrop.getY() + raindrop.getVerSpeed());
                        //相反方向
                        if (reserve) {
                            double result = raindrop.getHorSpeed() * -1;
                            raindrop.setHorSpeed(result);
                        }
                        //水平移动
                        raindrop.setX(raindrop.getX() + raindrop.getHorSpeed());

                        //雨滴到达了指定的下落位置,那么水滴要改变为水波
                        if (raindrop.getY() >= raindrop.getMaxY()) {
                            raindrop.changeStatus();
                        }
                    }else if(raindrop.getStatus() == RainStatus.RIPPLE){
                        raindrop.setScaleX(raindrop.getScaleX() * 1.03);
                        raindrop.setScaleY(raindrop.getScaleX());
                        raindrop.setOpacity(1 - raindrop.getScaleX() /3.0);
                        //如果水波缩放达到3倍,那么就应该改变状态为雨滴
                        if(raindrop.getScaleX() >=3){
                            //调整透明度和缩放为初始值
                            raindrop.setScaleX(1.0);
                            raindrop.setScaleY(raindrop.getScaleX());
                            raindrop.setOpacity(1.0);

                            raindrop.setX(random.nextDouble() * w);
                            raindrop.setVerSpeed(random.nextDouble() * 2.5 + 0.5);
                            raindrop.setHorSpeed(random.nextDouble() - 0.5);
                            raindrop.setMaxY( h- POOL_HEIGHT +  random.nextDouble() * POOL_HEIGHT);
                            raindrop.setY(0);
                            raindrop.changeStatus();
                        }
                    }
                }
                reserve = false;
            }
        };
        //启动动画
        animationTimer.start();
    }



    /**
     * 创建雪花
     */
    private void initRain() {
        for (int i = 0; i < flakeNum; i++) {
            Rain raindrop = new Rain();
            raindrop.setX(random.nextDouble() * w);
            raindrop.setVerSpeed(random.nextDouble() * 2.5 + 0.5);
            raindrop.setY(random.nextDouble() * h);
            //水平方向移动位置
            raindrop.setHorSpeed(random.nextDouble() - 0.5);
            raindrop.setMaxY( h- POOL_HEIGHT +  random.nextDouble() * POOL_HEIGHT);

            rainList.add(raindrop);
        }
        root.getChildren().addAll(rainList);
    }

    public static void main(String[] args) {
        launch(args);
    }
}
